package com.yswwpp.cross;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.UUID;

public class Entity  extends Coder implements Serializable, IProtocol
{

	private static final long serialVersionUID = -8811325765018674831L;

	// -------------------------------------

	private byte seg; // 协议标识
	private byte ver; // 协议版本
	private short tag; // 协议标签(即消息类型)
	private int len; // 协议长度
	private int ret; // 错误码
	private byte[] seq; // 序列号
	private short from; // 来源的平台 : 1  IOS；  2 安卓 ；   3 微信； 4 司机宝WEB ； 5司机宝 服务器；6金融服务器；7运营
	private short fromType; // 平台下的子系统或渠道

	// -------------------------------------

	public Entity capacity()throws Exception
	{
		len = 1 + 1 + 2 + 4 + 4 + PROTOCOL_SEQ_LEN + 2 + 2;
		return this;
	}

	// -------------------------------------

	public Entity()
	{
		setSeg(PROTOCOL_SEG);
		setVer(PROTOCOL_VER_DEFAULT);
		setTag(PROTOCOL_TAG_DEFAULT);
		setRet(MESSAGE_RET_OK);
		initSeq(PROTOCOL_SEQ_LEN);
		renderSeq();
		setFrom(FromEnum.FROM_UNKNOW.value());
	}

	public Entity(short tag,FromEnum fromEnum)
	{
		setSeg(PROTOCOL_SEG);
		setVer(PROTOCOL_VER_DEFAULT);
		setTag(tag);
		setRet(MESSAGE_RET_OK);
		initSeq(PROTOCOL_SEQ_LEN);
		renderSeq();
		setFrom(fromEnum.value());
	}

	public Entity(short tag, byte ver, String seq,FromEnum fromEnum)
	{
		setSeg(PROTOCOL_SEG);
		setVer(ver);
		setTag(tag);
		setRet(MESSAGE_RET_OK);
		initSeq(PROTOCOL_SEQ_LEN);
		if (seq != null && seq.length() == PROTOCOL_SEQ_LEN)
			setSeqStr(seq);
		else
			renderSeq();
		setFrom(fromEnum.value());
	}

	public Entity(short tag, byte ver, byte[] seq,FromEnum fromEnum)
	{
		setSeg(PROTOCOL_SEG);
		setVer(ver);
		setTag(tag);
		setRet(MESSAGE_RET_OK);
		initSeq(PROTOCOL_SEQ_LEN);
		setSeq(seq);
		setFrom(fromEnum.value());
	}

	public Entity(short tag, byte ver,FromEnum fromEnum)
	{
		setSeg(PROTOCOL_SEG);
		setVer(ver);
		setTag(tag);
		setRet(MESSAGE_RET_OK);
		initSeq(PROTOCOL_SEQ_LEN);
		renderSeq();
		setFrom(fromEnum.value());
	}

	// -------------------------------------

	public byte getSeg()
	{
		return seg;
	}

	public void setSeg(byte seg)
	{
		this.seg = seg;
	}

	public byte getVer()
	{
		return ver;
	}

	public void setVer(byte ver)
	{
		this.ver = ver;
	}

	public short getTag()
	{
		return tag;
	}

	public void setTag(short tag)
	{
		this.tag = tag;
	}

	public int getLen()
	{
		return len;
	}

	public void setLen(int len)
	{
		this.len = len;
	}

	public int getRet()
	{
		return ret;
	}

	public void setRet(int ret)
	{
		this.ret = ret;
	}

	public byte[] getSeq()
	{
		return seq;
	}

	public void setSeq(byte[] seq)
	{
		arraycopy(seq, this.seq);
	}

	public short getFrom()
	{
		return from;
	}

	public void setFrom(short from)
	{
		this.from = from;
	}

	public short getFromType()
	{
		return fromType;
	}

	public void setFromType(short fromType)
	{
		this.fromType = fromType;
	}
	// -------------------------------------

	protected void initSeq(int seqlen)
	{
		seq = new byte[seqlen];
	}

	// -------------------------------------

	public void arraycopy(byte[] src, byte[] dst)
	{
		int srclen = src.length;
		int dstlen = dst.length;
		if (srclen > dstlen)
			srclen = dstlen;
		System.arraycopy(src, 0, dst, 0, srclen);
	}

	// -------------------------------------

	// -------------------------------------

	public void renderSeq()
	{
		try
		{
			byte[] uuid = UUID.randomUUID().toString().replaceAll("\\-", "")
					.getBytes("UTF-8");
			setSeq(uuid);
		} catch (UnsupportedEncodingException e)
		{
		}
	}

	public void setSeqStr(String seq)
	{
		try
		{
			if (seq != null)
			{
				setSeq(seq.getBytes("UTF-8"));
			}
		} catch (UnsupportedEncodingException e)
		{
		}
	}

	public String getSeqStr()
	{
		try
		{
			return new String(getSeq(), "UTF-8");
		} catch (UnsupportedEncodingException e)
		{
			return null;
		}
	}
	
	public int capacityCurrent(Field[] fieldArr, Entity entity)
            throws IllegalArgumentException, IllegalAccessException
    {
        int length = 0;

        for (int i = 0; i < fieldArr.length; i++)
        {
            if ((Modifier.isStatic(fieldArr[i].getModifiers())
                    || Modifier.isFinal(fieldArr[i].getModifiers())))
                continue;
            Class<?> fieldTypeClass = fieldArr[i].getType();
            if (fieldTypeClass == byte.class || fieldTypeClass == Byte.class)
            {
                length += 1;
            } else if (fieldTypeClass == short.class
                    || fieldTypeClass == Short.class)
            {
                length += 2;
            } else if (fieldTypeClass == char.class
                    || fieldTypeClass == Character.class)
            {
                length += 2;
            } else if (fieldTypeClass == int.class
                    || fieldTypeClass == Integer.class)
            {
                length += 4;
            } else if (fieldTypeClass == long.class
                    || fieldTypeClass == Long.class)
            {
                length += 8;
            } else if (fieldTypeClass == float.class
                    || fieldTypeClass == Float.class)
            {
                length += 4;
            } else if (fieldTypeClass == double.class
                    || fieldTypeClass == Double.class)
            {
                length += 8;
            } else if (fieldTypeClass == boolean.class
                    || fieldTypeClass == Boolean.class)
            {
                length += 1;
            } else if (fieldTypeClass == String.class)
            {
                fieldArr[i].setAccessible(true);
                length += 4
                        + safeGetByteLength((String) fieldArr[i].get(entity));

            }else if (fieldTypeClass == byte[].class)
            {
                fieldArr[i].setAccessible(true);
                length += 4;
                if(fieldArr[i].get(entity)!=null)
                	length+=((byte[])fieldArr[i].get(entity)).length;

            } else
            {
                throw new IllegalAccessException(
                        "暂不支持编码的类型：" + fieldTypeClass.getName());
            }
        }

        return length;
    }
}
